Django 博客系统开发教程
1. Django 简介和特性
Django 是一个高级的 Python Web 框架,它鼓励快速开发和干净、实用的设计。Django 遵循 MVT(Model-View-Template)架构,提供了许多内置功能,如用户认证、内容管理、表单处理、文件上传等。
主要特性
- ORM(对象关系映射):简化数据库操作。
- 自动管理界面:快速生成管理后台。
- URL 路由:灵活的 URL 设计。
- 模板系统:强大的模板引擎。
- 表单处理:简化表单创建和验证。
- 安全性:内置多种安全机制。
2. 安装和环境设置
安装 Python
确保你的系统上安装了 Python 3.x。你可以通过以下命令检查:
python --version
安装 Django
使用 pip 安装 Django:
pip install django
创建虚拟环境
建议使用虚拟环境来隔离项目依赖:
python -m venv myenv
source myenv/bin/activate # 在 Windows 上使用 `myenv\Scripts\activate`
3. 项目结构和管理命令
创建 Django 项目
使用以下命令创建一个新的 Django 项目:
django-admin startproject myblog
项目结构
myblog/
manage.py
myblog/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
管理命令
- 运行开发服务器:
python manage.py runserver - 创建应用:
python manage.py startapp blog
4. MVT 架构
Model
模型是数据的唯一和明确的来源。它包含数据的基本字段和行为。
View
视图是处理请求并返回响应的逻辑。它可以是函数或类。
Template
模板是定义用户界面外观的文件。Django 使用模板语言来动态生成 HTML。
5. 第一个 Django 应用
创建应用
python manage.py startapp blog
定义模型
在 blog/models.py 中定义一个简单的模型:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField('date published')
注册模型
在 blog/admin.py 中注册模型:
from django.contrib import admin
from .models import Post
admin.site.register(Post)
创建和应用迁移
python manage.py makemigrations
python manage.py migrate
6. 模型定义和字段类型
常用字段类型
CharField:用于短字符串。TextField:用于长文本。IntegerField:用于整数。DateTimeField:用于日期和时间。ForeignKey:用于一对多关系。ManyToManyField:用于多对多关系。
示例
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
pub_date = models.DateField()
7. 数据库迁移
创建迁移
python manage.py makemigrations
应用迁移
python manage.py migrate
8. 查询集和管理器
查询集
查询集是从数据库中获取对象的集合。你可以使用过滤器、排序等操作。
示例
posts = Post.objects.filter(pub_date__year=2023)
管理器
管理器是 Django 模型用于数据库查询的接口。默认管理器是 objects。
9. 模型关系
一对多关系
使用 ForeignKey 字段:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
多对多关系
使用 ManyToManyField 字段:
class Publication(models.Model):
title = models.CharField(max_length=30)
class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)
10. 自定义模型方法
示例
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.title
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
11. 函数视图和类视图
函数视图
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world!")
类视图
from django.views import View
from django.http import HttpResponse
class IndexView(View):
def get(self, request):
return HttpResponse("Hello, world!")
12. URL 模式和命名
URL 模式
在 urls.py 中定义 URL 模式:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
命名 URL
<a href="{% url 'index' %}">Home</a>
13. 视图参数和请求处理
视图参数
def detail(request, post_id):
return HttpResponse(f"Post ID: {post_id}")
请求处理
def create_post(request):
if request.method == 'POST':
# 处理 POST 请求
pass
else:
# 处理 GET 请求
pass
14. 通用视图
示例
from django.views.generic import ListView, DetailView
from .models import Post
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post_detail.html'
15. 中间件
自定义中间件
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 请求前的处理
response = self.get_response(request)
# 响应后的处理
return response
16. 模板语法和标签
模板语法
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
模板标签
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}</p>
{% else %}
<p>Please log in.</p>
{% endif %}
17. 模板继承
基础模板
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Blog{% endblock %}</title>
</head>
<body>
<header>
<h1>My Blog</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>
子模板
<!-- post_detail.html -->
{% extends "base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
{% endblock %}
18. 上下文处理器
自定义上下文处理器
def my_context_processor(request):
return {'foo': 'bar'}
注册上下文处理器
在 settings.py 中:
TEMPLATES = [
{
'OPTIONS': {
'context_processors': [
'myapp.context_processors.my_context_processor',
],
},
},
]
19. 自定义模板标签和过滤器
自定义过滤器
from django import template
register = template.Library()
@register.filter
def lower_case(value):
return value.lower()
使用过滤器
{{ post.title|lower_case }}
20. 静态文件处理
配置静态文件
在 settings.py 中:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / "static",
]
使用静态文件
{% load static %}
<img src="{% static 'images/logo.png' %}" alt="Logo">
21. Django Form 类
创建表单
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
使用表单
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# 处理表单数据
pass
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
22. 表单验证
自定义验证
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
def clean_email(self):
email = self.cleaned_data['email']
if not email.endswith('@example.com'):
raise forms.ValidationError("Only example.com emails are allowed.")
return email
23. ModelForm
创建 ModelForm
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'pub_date']
使用 ModelForm
def create_post(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.save()
else:
form = PostForm()
return render(request, 'create_post.html', {'form': form})
24. 表单集 (Formsets)
创建表单集
from django.forms import formset_factory
from .forms import ContactForm
ContactFormSet = formset_factory(ContactForm, extra=2)
使用表单集
def contact_formset(request):
if request.method == 'POST':
formset = ContactFormSet(request.POST)
if formset.is_valid():
for form in formset:
# 处理每个表单
pass
else:
formset = ContactFormSet()
return render(request, 'contact_formset.html', {'formset': formset})
25. 文件上传处理
配置文件上传
在 settings.py 中:
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
创建表单
from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
处理文件上传
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})
26. 用户认证系统
内置认证视图
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
自定义用户模型
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
27. 权限和组
创建权限
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from .models import Post
content_type = ContentType.objects.get_for_model(Post)
permission = Permission.objects.create(
codename='can_publish',
name='Can Publish Posts',
content_type=content_type,
)
分配权限
user.user_permissions.add(permission)
28. 登录、注销和注册视图
登录视图
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
]
注销视图
urlpatterns = [
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
注册视图
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic
class SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
29. 基于类的权限控制
类视图权限控制
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DetailView
from .models import Post
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
template_name = 'post_detail.html'
30. Admin 站点定制
自定义 Admin 操作
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'pub_date', 'was_published_recently')
def make_published(self, request, queryset):
queryset.update(status='p')
make_published.short_description = "Mark selected posts as published"
31. 模型注册和配置
注册模型
from django.contrib import admin
from .models import Post
admin.site.register(Post)
配置模型
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'pub_date')
list_filter = ('pub_date',)
search_fields = ('title', 'content')
32. 自定义 Admin 操作
自定义操作
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
actions = ['make_published']